#ifndef  M_LOOP_H__
#define  M_LOOP_H__
#include "utils.hpp"
#include <vector>
#include <thread>
#include <mutex>
#include <atomic>
#include <condition_variable>
#include <functional>
#include "buffer.hpp"

namespace tclog{
    class AsyncLooper {

        public:
            using Functor = std::function<void(Buffer &buffer)>;
            using ptr = std::shared_ptr<AsyncLooper>;

            AsyncLooper(const Functor &cb): _running(true), _looper_callback(cb),
                _thread(std::thread(&AsyncLooper::worker_loop, this)) {
            }
            ~AsyncLooper() { stop(); }

            //生命周期管理
            void stop(){ 
                _running = false; 
                _pop_cond.notify_all();
                _thread.join();
            }

            //生产者接口
            void push(const std::string &msg){
                if (_running == false) return;
                {
                    std::unique_lock<std::mutex> lock(_mutex);
                    _push_cond.wait(lock, [&]{ return _tasks_push.writeAbleSize() >= msg.size(); });
                    _tasks_push.push(msg.c_str(), msg.size());
                }
                _pop_cond.notify_all();
            }

        private:
            //消费者逻辑
            void worker_loop(){
                while(1){
                    {
                        std::unique_lock<std::mutex> lock(_mutex);
                        if (_running == false && _tasks_push.empty()) { return; }
                        _pop_cond.wait(lock, [&]{ return !_tasks_push.empty() || !_running; });
                        _tasks_push.swap(_tasks_pop);
                    }
                    _push_cond.notify_all();
                    _looper_callback(_tasks_pop);
                    _tasks_pop.reset();
                }
                return;
            }
            
        private:
            Functor _looper_callback;
        private:
            std::mutex _mutex;
            std::atomic<bool> _running;   //线程运行状态

            std::condition_variable _push_cond; //生产者等待条件
            std::condition_variable _pop_cond;  //消费者等待条件

            Buffer _tasks_push;
            Buffer _tasks_pop;

            std::thread _thread;
    };
}

#endif